package com.qzh.JDBC;

import com.qzh.JDBC.annotation.EasyEntity;
import com.qzh.JDBC.annotation.EasyField;
import lombok.Data;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 扫描器，扫描包结构
 */
public final class Scanner {
    private List<Class> classList = new ArrayList<>();

    /**
     * 扫描指定目录下的所有类
     * @param packageName
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws URISyntaxException
     * @throws IOException
     */
    public   List<Class> scanPackage(String packageName) throws IOException, ClassNotFoundException, URISyntaxException, IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/');

        // 获取包路径下的所有资源（目录）
        Enumeration<URL> resources = classLoader.getResources(path);
        List<Class> classList =new ArrayList<>();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            classList.addAll(  scanDirectory(new File(resource.toURI()), packageName)) ;
        }
                this.classList = classList;
        return classList;
    }

    private   List<Class> scanDirectory(File directory, String packageName) throws ClassNotFoundException {
        List<Class> classList = new ArrayList<>();
        if (!directory.exists()) {
            return new ArrayList<>();
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                classList.addAll(scanDirectory(file, packageName + "." + file.getName())) ;
            } else if (file.getName().endsWith(".class")) {
                // 获取类的全名（包括包名）
                String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                try {
                    // 加载类
                    Class<?> clazz = Class.forName(className);
                    classList.add(clazz);
                    // 在这里处理类，例如打印类名
                   // System.out.println("Found class: " + clazz.getName());

                } catch (ClassNotFoundException e) {
                    // 类加载失败，可能是因为该类依赖于其他未找到的类
                    e.printStackTrace();
                }
            }
        }
        return classList;
    }

    /**
     * 根据注解筛选属性DBNAME
     * @param annotation
     * @return
     */
    public  Map<Class, Map<String ,OldAndNewName>> DBNameFilter( Class annotation){
        Map<Class, Map<String,OldAndNewName>> classFieldMap = new HashMap<>();
        List<Class> dblist =   classList.stream().filter(o->o.isAnnotationPresent(EasyEntity.class)).collect(Collectors.toList());
        for (int i = 0; i < dblist.size(); i++) {
            Class clazz =  dblist.get(i);
                String clazzName = clazz.getName();
            Map<String,OldAndNewName>fieldMap = new HashMap<>();
                      Field[] fields = clazz.getDeclaredFields();
                      if(  fields != null && fields.length > 0){
                          for (Field f :fields) {
                              OldAndNewName oldAndNewName = new OldAndNewName();
                                 String fieldName=   f.getName();
                                 oldAndNewName.setOldName(fieldName);
                                  Class  fieldClass =  f.getType();
                                  oldAndNewName.setType(fieldClass);
                                  if(f.isAnnotationPresent(annotation))
                                  {
                                      EasyField easyField = (EasyField) f.getAnnotation(annotation);
                                      fieldName = easyField.name();
                                  }
                              oldAndNewName.setNewName(fieldName);
                                fieldMap.put(oldAndNewName.getNewName(),oldAndNewName);
                          }
                      }
                  classFieldMap.put(clazz,fieldMap);

        }
        return classFieldMap;
    }
    @Data
    class OldAndNewName{
        // 旧名称
        private String oldName;
        // 新名称
        private String newName;
        // 类型
        private Class type;
    }
    public List<Class> getClassList() {
        return classList;
    }
}
